home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 110_01 / prolog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1984-03-02  |  11.3 KB  |  479 lines

  1. /*
  2.         PROLOG
  3.         written by Bob Pasky
  4.         36 Wiswall Rd.
  5.         Newton Centre, MA 01259
  6.  
  7.         as an adaptation of the TELNET program
  8.         written by Leor Zolman
  9.  
  10.     Compiled with BDS C 1.41; you may want to use the
  11.     modified "_spr" function (see printf.c), but it is
  12.     not required.
  13.  
  14.     The "modem" channel may be used to control a
  15.     PRO-LOG(tm) EPROM programmer. A .HEX file
  16.     (or portion thereof) may be burned into EPROM starting
  17.     at any EPROM address. A second function verifies the
  18.     contents of the EPROM against the .HEX file.
  19.  
  20.     During operation, typing a SPECIAL character followed
  21.     by one of the given code letters performs special
  22.     tasks:
  23.         q:    re-boots CP/M.
  24.         z:    clear screen
  25.         p:    program an EPROM.
  26.         v:    verify an EPROM.
  27.         d:    display directory of hex files
  28. */
  29.  
  30. #include "bdscio.h"
  31.  
  32. #define SPEC '@'    /* YOUR special character */
  33.  
  34. #define CLERS 0x1A    /* character to clear screen */
  35. #define HOME 1
  36. #define ACK 6
  37. #define NAK 0x15
  38. #define EOT 4
  39. #define ENQ 5
  40. #define STX 2
  41.  
  42. #define SRCHD1 17    /* search directory BDOS calls */
  43. #define SRCHDN 18
  44.  
  45. int fdb;
  46. int buflimit;
  47. char filnam[20];
  48. char hextab[16];
  49. char fcb[33];
  50. char bbuf[BUFSIZ];
  51. char obuf[BUFSIZ];
  52. char *buf;
  53.  
  54. /* For your particular configuration:
  55. ** define "MMREFIO" if you use memory
  56. ** reference i/o for modem control
  57. ** (peek-poke vs. inp-outp)
  58. */
  59. #ifdef    MMREFIO
  60. #define modin peek
  61. #define modout poke
  62. #endif
  63.  
  64. #ifndef MMREFIO
  65. #define modin inp
  66. #define modout outp
  67. #endif
  68.  
  69. main(argc,argv)
  70. int argc;
  71. char **argv;
  72. {
  73.     char c, *bufp, *i;
  74.     int fd, j;
  75.  
  76.     putchar(CLERS);
  77.     putchar(HOME);
  78.     strcpy(hextab,"0123456789ABCDEF");
  79.  
  80. /*    If your uart needs initializing, do it here:
  81. **    iuart(2);    /* set for input & output */
  82. */
  83.     printf ("\n\t\t\tEPROM Programmer ver. 1.A\n\n");
  84.  
  85.     instruct();
  86.  
  87.     modin(MDATA);    /* flush any garbage on line */
  88.  
  89.     bufp = buf = endext();
  90.     buflimit = topofmem() - 1000;    /* 1k = stack + safety factor */
  91.  
  92.     printf("\n%dK buffer space\n",(buflimit-endext())/1000 );
  93.     printf ("\n\nGet EPROM Programmer ready\n");
  94.  
  95. loop:    if (bios(2,0)) {    /* console status */
  96.         c = bios(3,0);    /* console in */
  97.         if (c != SPEC) outmod(c);
  98.         else {
  99.             printf("\nCommand: ");
  100.             switch (toupper(getchar())) {
  101.  
  102.             case '?':
  103.                 instruct();
  104.                 break;
  105.              case 'Q': printf ("uit");
  106.                 if (fd) {
  107.                     putc(CPMEOF,obuf);
  108.                     fflush(obuf);
  109.                     close(fd);
  110.                     }
  111.                    exit();
  112.  
  113.              case 'Z':  putchar(CLERS);
  114.                     break;
  115.  
  116.              case 'P':
  117.                 printf("rogram EPROM from HEX file");
  118.                 if (getfile() == FALSE) break;
  119.                 sendhex();
  120.                 close(fdb);
  121.                 printf("\nProgramming complete.\n");
  122.                 break;
  123.  
  124.              case 'V':
  125.                 printf("erify EPROM equals HEX file");
  126.                 if (getfile() == FALSE) break;
  127.                 comphex(buf,bufp);
  128.                 close(fdb);
  129.                 printf("\nVerificaton complete.\n");
  130.                 break;
  131.              case 'D':
  132.                 printf("irectory of HEX files");
  133.                 printf("\nDrive: ");
  134.                 strcat(gets(filnam),":????????.HEX");
  135.                 showfiles();
  136.                 break;
  137.               }}    /* end switch, end else */
  138.         }        /* end if kbready */
  139.         if ((modin(MSTAT) & MIMASK) ==
  140.             (MAHI ? MIMASK : 0)) {
  141.             c= modin(MDATA) & 0x7f;
  142.  
  143.             switch (c) {    /* some common ctrl codes */
  144.         case STX: printf("<STX>");
  145.             break;
  146.         case EOT: printf("<EOT>");
  147.             break;
  148.         case ACK: printf("<ACK>");
  149.             break;
  150.         case NAK: printf("<NAK>");
  151.             break;
  152.         default: putchar(c);
  153.             }    /* end switch */
  154.          }        /* end if modin */
  155.         goto loop;
  156. }                /* end main */
  157.  
  158. instruct()
  159. {
  160.     printf ("\nFollowing the command character (%c) use:",SPEC);
  161.     printf ("\n\td to show directory of HEX files");
  162.     printf ("\n\tp to program EPROM");
  163.     printf ("\n\tv to verify EPROM");
  164.     printf ("\n\tq to re-boot CP/M.");
  165.     printf ("\n\tz to clear screen");
  166.     printf ("\n\t? to show this text\n");
  167. }
  168.  
  169. getfile()
  170. {
  171.     printf("\nFilename: ");
  172.     strcat(gets(filnam),".HEX");
  173.     fdb=fopen(filnam,bbuf);
  174.     if (fdb==ERROR) {
  175.         printf("\nOpen error on %s\n",filnam);
  176.         return FALSE;
  177.        }
  178.     return TRUE;
  179. }
  180. showfiles()
  181. {
  182.     char c,i;
  183.  
  184.     setfcb(&fcb,filnam);
  185.     if ((c = bdos(SRCHD1,&fcb)) == 0xFF) {
  186.         printf("-- no files --\n");
  187.         return; }
  188.     else    showit(c);
  189.     i = 1;
  190.     while ((c = bdos(SRCHDN,&fcb)) != 0xFF) {
  191.         putchar ((i++ % 4) ? ' ' : '\n');
  192.         showit(c); }
  193.     printf("\nDirectory complete\n");
  194. }
  195.  
  196. /* The .HEX file format --
  197. **    :     - start of block character,
  198. **    hh    - two hex digits = # of bytes in this block
  199. **          a 00 count indicates end of file,
  200. **    hhhh    - four hex digits = load address of this block,
  201. **    hh    - two hex digits = unused,
  202. **    hh    - pair of hex digits = first data byte
  203. **    ...    - pairs of hex digits = remaining data bytes
  204. **    hh    - last pair of hex digits = sumcheck for block,
  205. **          (ignored by this program)
  206. **    <cr><lf>- carriage return, line feed.
  207. */
  208. /* The Pro-Log expects --
  209. **    hhh    - start address (for 8k to 32k EPROMS),
  210. **    hhh    - end address,
  211. **    P    - upper case 'P' = program.
  212. ** The Pro-Log returns --
  213. **    <ACK> or <NAK>
  214. **        - a NAK says the chip is not blank in the
  215. **          section to be programmed,
  216. **    <STX>    - says start sending data.
  217. ** The Pro-Log expects --
  218. **    hh    - two hex digits = data byte, <space> or <cr> is ignored.
  219. ** The Pro-Log returns --
  220. **    <ACK> or <NAK> or <EOT>
  221. **        - an ACK = sucessful program of location,
  222. **          NAK = error, reading location did not return data expected,
  223. **          EOT = end address has been reached.
  224. ** ...continue for each data byte until end address reached.
  225. */
  226.  
  227. sendhex()
  228. {
  229. char a1,a2,c,h1,h2,m;
  230. int f,l,pe,ps,d1,i;
  231. int count,errcnt,total;
  232. char inputbuf[16];
  233.  
  234.     errcnt=total=0;
  235.     if (!getaddress(&f,&l,&ps,&pe)) return;    /* user quits */
  236.  
  237.     /* start by sending PROLOG the start and end addresses */
  238.     twohexout (ps,pe);
  239.     outmod ('P');    /* a P puts PROLOG into program mode */
  240.  
  241.     /* The PROLOG will send a NAK if the PROM is not blank */
  242.     while((m=getmod())!=ACK && m!=NAK && m!=ENQ);
  243.     if (m==NAK) {
  244.         printf("\nNOT ERASED, continue? ");
  245.         if (tolower(getchar())!='y') goto endaddr;
  246.         }
  247.     if (m==ENQ) return;
  248.     /*
  249.     ** Now read the .HEX file until the first address 
  250.     ** to be programmed is found
  251.     */
  252.     while ((c=getc(bbuf)) != CPMEOF)
  253.         {
  254.         if (c != ':') continue;    /* look for block start char */
  255.         a1 = getc(bbuf)-'0';    /* get # of bytes in block */
  256.         a2 = getc(bbuf)-'0';
  257.         if (a1==0 && a2==0) break; /* end of file */
  258.         count = (a1<<4) + a2;    /* convert count to integer */
  259.  
  260.         for (i = 0; i<4; i++) {
  261.             inputbuf[i]=getc(bbuf);
  262.             }
  263.         inputbuf[4]='\0';    /* end the string */
  264.         sscanf(inputbuf,"%x",&d1);    /* convert to integer */
  265.         printf ("\nBlock address: %x",d1);
  266.  
  267.         getc(bbuf); getc(bbuf); /* ignore next 2 bytes */
  268.  
  269.     /* looking for first location to be programmed: */
  270.         if ( d1+count < f ) continue;
  271.         for (i=0; i<count; i++,d1++)
  272.             {
  273.             if ( d1 > l ) {
  274.                 printf ("\nEnd address reached.");
  275.                 goto endaddr; }
  276.             putchar (i%16 ? ' ' : '\n');
  277.  
  278.             h1=getc(bbuf);    /* get next 2 hex chars */
  279.             h2=getc(bbuf);
  280.  
  281.             if (d1 < f) printf ("xx"); /* byte not being sent */
  282.             else {            /* send byte to Prolog */
  283.                 printf ("%c%c",h1,h2);
  284.                 outmod(h1); outmod(h2);
  285.                 total++;
  286.  
  287.                 while ((m=getmod()) != ACK &&
  288.                     m != NAK && m != EOT) ;
  289.                 if (m==NAK) { putchar ('#'); errcnt++; }
  290.                 if (m==EOT) {
  291.                     printf("\n<EOT>");
  292.                     goto endaddr; }
  293.                 } /* end else */
  294.             } /* end for */
  295.         } /* end while */
  296. endaddr:
  297.     printf("\n%4d error",errcnt);
  298.     if (errcnt!=1) putchar ('s');
  299.     printf (" out of %d location",errcnt,total);
  300.     if (total!=1) putchar ('s');
  301.     printf (" programmed.");
  302.  
  303. } /* end sendhex */
  304.  
  305. /* VERIFY EPROM
  306.     Compares .HEX file with List data from PROLOG
  307. */
  308. comphex(buf,bufp)
  309. char *bufp, buf[];
  310.  
  311. {
  312. char *i;
  313. char a1,a2,c,h1,h2,j;
  314. int f,l,pe,ps,d1,d2;
  315. int count,errcnt,total;
  316. char inputbuf[10];
  317.  
  318.     i = buf;
  319.     errcnt=total=0;
  320.     if (!getaddress(&f,&l,&ps,&pe)) return;
  321.  
  322.     twohexout(ps,pe);
  323.     outmod ('L');
  324.     while ((c=getmod()) != 'L' && c != ENQ) ; /* wait for echo of L */
  325.     if (c == ENQ) return;
  326.     bufp=buf;
  327.     while ((c=getmod())!=EOT)
  328.         {
  329.         if ( c & 0x7f ) *bufp++ = c;
  330.         if (bufp == buflimit)
  331.             {
  332.             printf("\nBuffer full.\n");
  333.             break;
  334.             }
  335.         } /* end while */
  336.     while ((c=getc(bbuf))!= CPMEOF)
  337.         {
  338.         if (c != ':') continue;
  339.         a1 = getc(bbuf)-'0';
  340.         a2 = getc(bbuf)-'0';
  341.         count = (a1<<4) + a2;
  342.         if (count == 0) break;
  343.  
  344.         for (j = 0; j < 4; j++) {
  345.             inputbuf[j] = getc(bbuf);
  346.             }
  347.         inputbuf[4] = '\0';
  348.         sscanf(inputbuf,"%x",&d1);
  349.         if ( d1+count < f ) continue;
  350.  
  351.         getc(bbuf); getc(bbuf);    /*ignore next 2 bytes    */
  352.  
  353.         for (a1 = 0; a1 < count; a1++,d1++)
  354.         {
  355.             if (d1 > 1) {
  356.                 printf("\nEnd address reached.");
  357.                 goto endcomp;
  358.             }
  359.             putchar( a1%16 ? ' ' : '\n');
  360.             h1 = getc(bbuf);
  361.             h2 = getc(bbuf);
  362.  
  363.             if (d1 < f) printf("xx");
  364.             else {
  365.                 printf("%c%c",h1,h2);
  366.                 if (i >= bufp) break;
  367.                 while (*i < '0' || *i >'F') i++;
  368.  
  369.                 c = *i++;    /* get first pair */
  370.                 if (c != h1 || *i != h2) {
  371.                     printf("#%c%c",c,*i);
  372.                     errcnt++;
  373.                 }
  374.                 i++;
  375.             } /* end else */
  376.         } /* end for */
  377.     } /* end while */
  378.  
  379. endcomp:
  380.     printf("\n%4d error",errcnt);
  381.     if(errcnt != 1) putchar ('s');
  382. } /* end comphex */
  383.  
  384. getaddress(first,last,pstart,pend)
  385. int *first,*last,*pstart,*pend;
  386. {
  387. char c,inputbuf[16];
  388.  
  389. esa:    *pstart = *first = 0;
  390.     *last = 0x7FF;    /* default to 16k EPROM    */
  391.     printf("\nEnter program starting address: (0000) ");
  392.     gets(inputbuf);
  393.     if(inputbuf[0]) sscanf(inputbuf,"%x",first);
  394.  
  395.     printf("\nEnter program ending address:   (07FF) ");
  396.     gets(inputbuf);
  397.     if(inputbuf[0]) sscanf(inputbuf,"%x",last);
  398.  
  399.     if(*last < *first) {
  400.         printf("\nStart higher than end. Try again.");
  401.         goto esa;
  402.         }
  403.  
  404.     printf("\nEnter PROM starting address: (0000) ");
  405.     gets(inputbuf);
  406.     if(inputbuf[0]) sscanf(inputbuf,"%x",pstart);
  407.     *pstart &= 0xFFF;    /* mask for 16k PROM    */
  408.     *pend = (*last - *first + *pstart) & 0xFFF;
  409.  
  410.     printf("\nProgram address: %04x", *first);
  411.     printf("to %04x", *last);
  412.     printf("\ninto PROM location:  %03x", *pstart);
  413.     printf("to  %03x", *pend);    printf("\nAddresses ok? (Yes/No/Quit) ");
  414.     if( (c = tolower(getchar()) ) == 'q') return(0);
  415.     if(c!='y') goto esa;
  416.     return(1);
  417. } /* end getaddress */
  418.  
  419. twohexout(ps,pe)
  420. int ps,pe;
  421. {
  422.     outmod(hextab[ (ps >> 8) & 0xF ]);
  423.     outmod(hextab[ (ps >> 4) & 0xF ]);
  424.     outmod(hextab[ ps & 0xF ]);
  425.     outmod(hextab[ (pe >> 8) & 0xF ]);
  426.     outmod(hextab[ (pe >> 4) & 0xF ]);
  427.     outmod(hextab[ pe & 0xF ]);
  428. }
  429.  
  430. getmod()
  431. {
  432.     int time;
  433.  
  434.     time = 0;
  435.     while( (modin(MSTAT) & MIMASK) != (MAHI ? MIMASK : 0) )
  436.         if (!++time) {
  437.             printf("time out on rec'v\n");
  438.             return (ENQ); 
  439.         }
  440.     return ( modin(MDATA) & 0x7F);
  441. }
  442.  
  443. /* send char to serial port */
  444. outmod(c)
  445. char c;
  446. {
  447.     int time;
  448.  
  449.     time = 0;
  450.     while( (modin(MSTAT) & MOMASK) == (MAHI ? 0 : MOMASK) )
  451.         if (!++time) {
  452.             printf("time out on xmit\n");
  453.             return;
  454.         }    modout(MDATA,c);
  455.  
  456. }
  457.  
  458. /* Prints a filename from a directory sector, assumed to be at BASE+80h
  459. **    offset is the file number returned by a bdos call to find an
  460. **    ambiguous (wildcarded) filename, but need only be a value
  461. **    between 0 and 63.
  462. */
  463. showit(offset)
  464. int offset;
  465. {
  466.     /* find start of filename within dma buffer address.
  467.        there are 4 files per sector or 32 bytes per entry.
  468.     */
  469.     offset = BASE + 0x80 + ((offset & 3) * 32);
  470.     printf ("%14s",offset+1);
  471.         /* this works only 'cause there is a zero byte
  472.            after the file type (i.e. the extent = 0);    */
  473. }
  474. /* end of program - prolog */
  475.  
  476.  
  477.  
  478.  
  479.